package com.xiaoshuidi.cloud.module.contract.service.bill;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xiaoshuidi.cloud.framework.common.pojo.CommonResult;
import com.xiaoshuidi.cloud.framework.common.util.json.JsonUtils;
import com.xiaoshuidi.cloud.module.bpm.api.task.BpmProcessInstanceApi;
import com.xiaoshuidi.cloud.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import com.xiaoshuidi.cloud.module.bpm.enums.BpmBusinessTypeEnum;
import com.xiaoshuidi.cloud.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import com.xiaoshuidi.cloud.module.bpm.mq.message.BpmProcessInstanceResultEvent;
import com.xiaoshuidi.cloud.module.contract.dal.dataobject.approval.ContractApprovalConfigDO;
import com.xiaoshuidi.cloud.module.contract.dal.dataobject.approval.ContractApprovalDO;
import com.xiaoshuidi.cloud.module.contract.dal.dataobject.bill.OrderFeesDO;
import com.xiaoshuidi.cloud.module.contract.dal.dataobject.bill.ReadjustDO;
import com.xiaoshuidi.cloud.module.contract.dal.dataobject.bill.RentOrderDO;
import com.xiaoshuidi.cloud.module.contract.dal.mysql.approval.ContractApprovalConfigMapper;
import com.xiaoshuidi.cloud.module.contract.dal.mysql.approval.ContractApprovalMapper;
import com.xiaoshuidi.cloud.module.contract.dal.mysql.bill.OrderFeesMapper;
import com.xiaoshuidi.cloud.module.contract.dal.mysql.bill.ReadjustRecordMapper;
import com.xiaoshuidi.cloud.module.contract.dal.mysql.bill.RentOrderMapper;
import com.xiaoshuidi.cloud.module.contract.enums.ApproveTypeEnum;
import com.xiaoshuidi.cloud.module.contract.service.approval.ContractApprovalService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.xiaoshuidi.cloud.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.xiaoshuidi.cloud.framework.security.core.util.SecurityFrameworkUtils.getLoginUser;
import static com.xiaoshuidi.cloud.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static com.xiaoshuidi.cloud.module.contract.enums.ErrorCodeConstants.CONTRACT_ORDERFEES_NOT_EXISTS;
import static com.xiaoshuidi.cloud.module.contract.enums.ErrorCodeConstants.READJUST_AMOUNT_RESULT_DATA_ERROR;

/**
 * 冲调记录
 */
@Slf4j
@Service
public class ReadjustRecordServiceImpl implements ReadjustRecordService{

    @Autowired
    private OrderFeesMapper orderFeesMapper;

    @Autowired
    private ReadjustRecordMapper readjustRecordMapper;
    @Resource
    private BpmProcessInstanceApi bpmProcessInstanceApi;
    @Resource
    private ContractApprovalService contractApprovalService;
    @Resource
    private ContractApprovalMapper approvalMapper;
    @Resource
    private ContractApprovalConfigMapper contractApprovalConfigMapper;
    @Resource
    private RentOrderMapper rentOrderMapper;
    @Value("${spring.application.name}")
    private String applicationName;


    /**
     * 根据账单明细id, 查询
     * @param updateReqVO
     * @return
     */
    @Override
    public List<ReadjustDO> queryByOrderFeesId(ReadjustDO updateReqVO) {
        return readjustRecordMapper.selectList(new QueryWrapper<ReadjustDO>().lambda().eq(ReadjustDO::getOrderfeesId, updateReqVO.getOrderfeesId())
                .orderBy(true,false,ReadjustDO::getCreateTime));
    }

    /**
     * 批量修改账单明细
     * @param updateReqVOS
     */
    public void batchUpdate(List<ReadjustDO> updateReqVOS){
        updateReqVOS.forEach(item->{
            // 校验存在
            OrderFeesDO orderFeesDO = orderFeesMapper.selectById(item.getOrderfeesId());
            if (orderFeesDO == null) {
                throw exception(CONTRACT_ORDERFEES_NOT_EXISTS);
            }
            BigDecimal readjustAmount = item.getAmount();
            if(readjustAmount.compareTo(new BigDecimal(0))<0){
                if(readjustAmount.abs().compareTo(orderFeesDO.getAmount())>=0)
                    throw exception(READJUST_AMOUNT_RESULT_DATA_ERROR);
            }
            item.setDeptId(orderFeesDO.getDeptId());
            //增加费项
            item.setFeeSort(orderFeesDO.getFeeSort());
            item.setFeeName(orderFeesDO.getFeeName());
            item.setFeeId(orderFeesDO.getFeeId());
        });

        //入库
        updateReqVOS.forEach(item->{
            try{
                OrderFeesDO orderFeesDO = orderFeesMapper.selectById(item.getOrderfeesId());
                item.setApproveStatus("pending");

                //合同配置房间
                LambdaQueryWrapper<ContractApprovalDO> wrapper=new LambdaQueryWrapper<>();
                wrapper.eq(ContractApprovalDO::getApartmentId,item.getDeptId());
                wrapper.eq(ContractApprovalDO::getType,"readjustOrderFee");
                wrapper.eq(ContractApprovalDO::getDeleted,0);
                ContractApprovalDO contractApprovalDO = approvalMapper.selectOne(wrapper);
                if(contractApprovalDO != null){
                    //查询开关
                    LambdaQueryWrapper<ContractApprovalConfigDO> lambdaQueryWrapper=new LambdaQueryWrapper();
                    lambdaQueryWrapper.eq(ContractApprovalConfigDO::getId,contractApprovalDO.getApprovalId());
                    lambdaQueryWrapper.eq(ContractApprovalConfigDO::getDeleted,0);

                    ContractApprovalConfigDO approvalConfigDO = contractApprovalConfigMapper.selectOne(lambdaQueryWrapper);
                    if (approvalConfigDO != null && approvalConfigDO.getIsOpen() == 0) {
                        item.setApproveStatus("notReview");
                        //新增
                        readjustRecordMapper.insert(item);

                        //修改账单金额
                        RentOrderDO rentOrderDO = rentOrderMapper.selectById(orderFeesDO.getOrderId());
                        //先去掉之前的冲调金额, 再重新计算
                        BigDecimal readjustAmount = orderFeesDO.getReadjustAmount();
                        rentOrderDO.setTotalAmount(rentOrderDO.getTotalAmount().subtract(readjustAmount).add(item.getAmount()));
                        //查询之前冲调金额
                        if (rentOrderDO.getReadjustAmount() == null)
                            rentOrderDO.setReadjustAmount(item.getAmount());
                        else
                            rentOrderDO.setReadjustAmount(rentOrderDO.getReadjustAmount().subtract(readjustAmount).add(item.getAmount()));
                        rentOrderMapper.updateById(rentOrderDO);
                        //修改账单明细
                        OrderFeesDO updateOrderFeesDO = new OrderFeesDO();
                        updateOrderFeesDO.setId(item.getOrderfeesId());
                        updateOrderFeesDO.setReadjustAmount(item.getAmount());
                        updateOrderFeesDO.setRemark(item.getDetails());
                        orderFeesMapper.updateById(updateOrderFeesDO);
                        return;
                    }
                }
                String idStr = IdUtil.getSnowflake(1, 20).nextIdStr();
                item.setProcessInstanceId(idStr);
                //新增
                readjustRecordMapper.insert(item);
                //审核流程
                String processDefinitionKey = contractApprovalService.getByRoomIdAndMark(orderFeesDO.getDeptId(), ApproveTypeEnum.READJUST_ORDER_FEE.getMsg());
                createReadjustProcessInstance(orderFeesDO,item, processDefinitionKey);
            }catch (Exception e){
                e.printStackTrace();
            }
        });
    }

    /**
     * 冲调审批回调
     * @param event
     */
    @Override
    public void callBackReadjust(BpmProcessInstanceResultEvent event) {
        String businessKey = event.getBusinessKey();
        //查询审核流程
        QueryWrapper<ReadjustDO> wrapper = new QueryWrapper<>();
        wrapper.eq("process_instance_id",businessKey);
        ReadjustDO readjustDO = readjustRecordMapper.selectOne(wrapper);
        if(BpmProcessInstanceResultEnum.APPROVE.getResult().equals(event.getResult())){
            //修改账单明细
            OrderFeesDO orderFeesDO = orderFeesMapper.selectById(readjustDO.getOrderfeesId());
            orderFeesDO.setReadjustAmount(readjustDO.getAmount());
            orderFeesDO.setRemark(readjustDO.getDetails());
            orderFeesMapper.updateById(orderFeesDO);
            //修改账单金额
            RentOrderDO rentOrderDO = rentOrderMapper.selectById(orderFeesDO.getOrderId());
            rentOrderDO.setTotalAmount(rentOrderDO.getTotalAmount().add(readjustDO.getAmount()));
            rentOrderDO.setReadjustAmount(readjustDO.getAmount());
            rentOrderMapper.updateById(rentOrderDO);
            //审核成功
            readjustDO.setApproveStatus("pass");
            readjustRecordMapper.updateById(readjustDO);
        }else {
            //审核失败
            readjustDO.setApproveStatus("reject");
            readjustRecordMapper.updateById(readjustDO);
        }
    }


    private String createReadjustProcessInstance(OrderFeesDO orderFeesDO,ReadjustDO readjustDO, String processDefinitionId){

        // 工作流参数
        BpmProcessInstanceCreateReqDTO bpmProcessInstanceCreateReqDTO = new BpmProcessInstanceCreateReqDTO();
        bpmProcessInstanceCreateReqDTO.setProcessDefinitionKey(processDefinitionId);
        bpmProcessInstanceCreateReqDTO.setBusinessType(BpmBusinessTypeEnum.READJUST_ORDER_FEE.name());
        bpmProcessInstanceCreateReqDTO.setBusinessKey(readjustDO.getProcessInstanceId());
        Map<String, Object> variables = new HashMap<>();
        variables.put("createName", Objects.nonNull(getLoginUser())?getLoginUser().getNickname():"");
        variables.put("createId", Objects.nonNull(getLoginUser())?getLoginUser().getId():null);
        variables.put("orderFeesDO", orderFeesDO);
        variables.put("readjustDO", readjustDO);
        bpmProcessInstanceCreateReqDTO.setVariables(variables);
        bpmProcessInstanceCreateReqDTO.setTenantId(Objects.nonNull(getLoginUser())?getLoginUser().getTenantId():null);
        bpmProcessInstanceCreateReqDTO.setServiceName(applicationName);
        BpmProcessInstanceCreateReqDTO.ExtendDto extendDto = new BpmProcessInstanceCreateReqDTO.ExtendDto();
        extendDto.setRoomId("");
        extendDto.setContractId(null);
        extendDto.setContractNo("");
        extendDto.setOwnerContractId(null);
        extendDto.setRoomName("");
        extendDto.setApartmentId(orderFeesDO.getDeptId());
        extendDto.setApartmentName(null);
        extendDto.setCustomName("");
        extendDto.setCustomPhone("");
        bpmProcessInstanceCreateReqDTO.setExtendDto(extendDto);
        CommonResult<String> processInstance = bpmProcessInstanceApi.createProcessInstance(getLoginUserId(), bpmProcessInstanceCreateReqDTO);
        log.info("processInstance:{}", JsonUtils.toJsonString(processInstance));
        return processInstance.getCheckedData();
    }
}
